package com.gaussian.property.admin.module.biz.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.gaussian.property.admin.module.biz.vo.projectconfig.AddProjectCheckTable;
import com.gaussian.property.admin.module.biz.vo.projectconfig.EditProjectCheckTable;
import com.gaussian.property.admin.module.biz.vo.projectconfig.PageQueryProjectRequest;
import com.gaussian.property.module.biz.entity.OptRole;
import com.gaussian.property.module.biz.entity.Project;
import com.gaussian.property.module.biz.entity.ProjectCheckTable;
import com.gaussian.property.module.biz.entity.ProjectCheckTableRole;
import com.gaussian.property.module.biz.mapper.ProjectCheckTableMapper;
import com.gaussian.property.module.biz.service.IOptRoleService;
import com.gaussian.property.module.biz.service.IProjectCheckTableRoleService;
import com.gaussian.property.module.biz.service.IProjectCheckTableService;
import com.gaussian.property.module.biz.service.IProjectService;
import com.gaussian.property.module.biz.vo.projectchecktable.PageQueryProjectTableRequest;
import com.gaussian.property.module.biz.vo.projectchecktable.ProjectCheckTableDetail;
import com.songqi.common.core.constant.Constants;
import com.songqi.common.core.constant.HttpStatus;
import com.songqi.common.core.domain.OptionVo;
import com.songqi.common.core.domain.R;
import com.songqi.common.core.domain.page.PageDataInfo;
import com.songqi.common.core.exception.CustomException;
import com.songqi.common.core.utils.BeanCopyUtil;
import com.songqi.common.core.validationgroup.AddGroup;
import com.songqi.common.mybatis.core.util.MyBatisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;

import javax.annotation.Resource;
import javax.validation.groups.Default;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: songqi(13776346982)
 * @date: 2024/4/16 15:33
 */
@Service
@Slf4j
public class ProjectCheckTableService {

    @Resource
    private IProjectCheckTableService iProjectCheckTableService;
    @Resource
    private IProjectCheckTableRoleService iProjectCheckTableRoleService;
    @Resource
    private ProjectCheckTableMapper projectCheckTableMapper;
    @Resource
    private IOptRoleService iOptRoleService;
    @Resource
    private IProjectService iProjectService;

    @Value("${gaussian.api.queryProject}")
    private String queryProjectUrl;

    public IPage<ProjectCheckTableDetail> pageQueryProjectTable(PageQueryProjectTableRequest queryRequest) {
        IPage<ProjectCheckTableDetail> iPage = MyBatisUtils.buildPage(queryRequest);
        IPage<ProjectCheckTableDetail> pageData = projectCheckTableMapper.pageQueryProjectTable(iPage, queryRequest);
        if(CollectionUtil.isNotEmpty(pageData.getRecords())){
            for (ProjectCheckTableDetail record : pageData.getRecords()) {
                record.setOptRoleNameList(getProjectCheckTabaleOptRoleNameList(record.getProjectCheckTableId()));
            }
        }
        return pageData;
    }

    /**
     * 从高仙接口中分页查询项目信息
     * @param queryProjectRequest
     * @return
     */
    public PageDataInfo<OptionVo> pageQueryProject(PageQueryProjectRequest queryProjectRequest) {
        PageDataInfo<OptionVo> pageDataInfo = new PageDataInfo<>();
        String url = queryProjectUrl + "?pageNum=" + queryProjectRequest.getPageNum() +
                "&pageSize=" + queryProjectRequest.getPageSize();
        if(StrUtil.isNotBlank(queryProjectRequest.getItemName())){
            url += "&itemName=" + queryProjectRequest.getItemName();
        }
        String frontRequestId = "pc-" + System.currentTimeMillis() + "-" + RandomUtil.randomString(12);
        log.info("调用高仙{}请求参数：ics-authorization={},Authorization={},front-request-id={}",
                url, queryProjectRequest.getIcsAuthorization(), queryProjectRequest.getAuthorization(), frontRequestId);
        HttpResponse response = HttpRequest.get(url)
                .header("ics-authorization", queryProjectRequest.getIcsAuthorization())
                .header("Authorization", queryProjectRequest.getAuthorization())
                .header("front-request-id", frontRequestId).execute();
        if(response.isOk()){
            String respBody = response.body();
            log.info("调用高仙{}返回结果：{}", url, respBody);
            R r = JSONUtil.toBean(respBody, R.class);
            if(r.getCode() == HttpStatus.SUCCESS){
                // 解析数据
                JSONObject jsonObject = (JSONObject) r.getData();

                pageDataInfo.setPageNum(((Integer) jsonObject.get("pageNum")).longValue());
                pageDataInfo.setPageSize(((Integer) jsonObject.get("pageSize")).longValue());
                pageDataInfo.setTotal(((Integer) jsonObject.get("total")).longValue());
                JSONArray jsonArray = (JSONArray) jsonObject.get("list");
                List<OptionVo> optionVoList = new ArrayList<>();

                if(!jsonArray.isEmpty()){
                    // 遍历JSONArray中的每个元素
                    for (Object object : jsonArray) {
                        JSONObject json = (JSONObject) object;
                        OptionVo optionVo = new OptionVo();
                        optionVo.setName(json.get("itemName").toString());
                        optionVo.setValue(json.get("itemId") + "");
                        optionVoList.add(optionVo);
                    }
                }
                pageDataInfo.setRows(optionVoList);
            }else if(16 == r.getCode()){
                log.error("调用高仙{}失败。失败信息：{}", url, r.getMsg());
                throw new CustomException("查询项目列表失败。错误原因:IAM Token过期，请从ics后台重新打开");
            }else {
                log.error("调用高仙{}失败。失败信息：{}", url, r.getMsg());
                throw new CustomException("查询项目列表失败。错误原因：" + r.getMsg());
            }
        }else {
            log.error("连接超时");
            throw new CustomException("调用高仙接口发生异常");
        }
        return pageDataInfo;
    }



    /**
     * 新增项目绑定的稽核表
     * @param addProjectConfig
     */
    @Transactional(rollbackFor = Exception.class)
    public void add(AddProjectCheckTable addProjectConfig) {
        String projectId = addProjectConfig.getProjectId();
        String checkTableId = addProjectConfig.getCheckTableId();
        LambdaQueryWrapper<ProjectCheckTable> queryWrapper = new LambdaQueryWrapper<ProjectCheckTable>()
                .eq(ProjectCheckTable::getProjectId, projectId)
                .eq(ProjectCheckTable::getCheckTableId, checkTableId)
                .eq(ProjectCheckTable::getStatus, Constants.ENABLE);
        if(iProjectCheckTableService.count(queryWrapper) > 0){
            throw new CustomException("该项目已配置此稽核标准，请重新选择");
        }
        Project project = iProjectService.getById(addProjectConfig.getProjectId());
        if(project == null){
            project = new Project();
            project.setProjectId(addProjectConfig.getProjectId());
        }
        project.setProjectName(addProjectConfig.getProjectName());
        iProjectService.saveOrUpdate(project);

        ProjectCheckTable projectCheckTable = BeanCopyUtil.copyProperties(addProjectConfig, ProjectCheckTable.class);
        projectCheckTable.setStatus(Constants.ENABLE);
        projectCheckTable.setProjectName(project.getProjectName());
        iProjectCheckTableService.save(projectCheckTable);
        saveProjectTableRoleIdList(addProjectConfig.getRoleIdList(), projectCheckTable.getProjectCheckTableId());
    }


    /**
     * 编辑项目绑定的稽核表
     * @param editProjectConfig
     */
    @Transactional(rollbackFor = Exception.class)
    public void edit(EditProjectCheckTable editProjectConfig) {
        String projectId = editProjectConfig.getProjectId();
        String checkTableId = editProjectConfig.getCheckTableId();
        String projectCheckTableId = editProjectConfig.getProjectCheckTableId();
        LambdaQueryWrapper<ProjectCheckTable> queryWrapper = new LambdaQueryWrapper<ProjectCheckTable>()
                .eq(ProjectCheckTable::getProjectId, projectId)
                .eq(ProjectCheckTable::getCheckTableId, checkTableId)
                .eq(ProjectCheckTable::getProjectCheckTableId, projectCheckTableId);
        ProjectCheckTable projectCheckTable = iProjectCheckTableService.getOne(queryWrapper);
        if(projectCheckTable == null){
            throw new CustomException("【参数错误】项目绑定的稽核表id不存在");
        }

        projectCheckTable.setCheckPeriod(editProjectConfig.getCheckPeriod());
        projectCheckTable.setCountPerPeriod(editProjectConfig.getCountPerPeriod());
        projectCheckTable.setPassingScore(editProjectConfig.getPassingScore());
        iProjectCheckTableService.updateById(projectCheckTable);

        delProjectTableRoleIdList(projectCheckTableId);
        saveProjectTableRoleIdList(editProjectConfig.getRoleIdList(), projectCheckTable.getProjectCheckTableId());
    }


    /**
     * 删除项目绑定的稽核表
     * @param projectCheckTableId
     */
    public void delete(String projectCheckTableId) {
        iProjectCheckTableService.removeById(projectCheckTableId);
    }


    /**
     * 停用/启用项目绑定的稽核表。返回更新后的状态。1-启用，0-停用
     * @param projectCheckTableId
     * @return
     */
    public Integer changeStatus(String projectCheckTableId) {
        ProjectCheckTable projectCheckTable = iProjectCheckTableService.getById(projectCheckTableId);
        if(projectCheckTable != null){
            int status = projectCheckTable.getStatus() ^ 1;
            projectCheckTable.setStatus(status);
            iProjectCheckTableService.updateById(projectCheckTable);
            return status;
        }
        return null;
    }


    private List<String> getProjectCheckTabaleOptRoleNameList(String projectCheckTableId) {
        LambdaQueryWrapper<ProjectCheckTableRole> queryWrapper = new LambdaQueryWrapper<ProjectCheckTableRole>()
                .eq(ProjectCheckTableRole::getProjectCheckTableId, projectCheckTableId);
        List<ProjectCheckTableRole> list = iProjectCheckTableRoleService.list(queryWrapper);
        if(CollectionUtil.isNotEmpty(list)){
            List<String> optRoleIdList = list.stream().map(ProjectCheckTableRole::getOptRoleId).collect(Collectors.toList());
            LambdaQueryWrapper<OptRole> roleQueryWrapper = new LambdaQueryWrapper<OptRole>()
                    .in(OptRole::getOptRoleId, optRoleIdList);
            List<OptRole> optRoleList = iOptRoleService.list(roleQueryWrapper);
            return optRoleList.stream().map(OptRole::getName).collect(Collectors.toList());
        }
        return null;
    }

    private void delProjectTableRoleIdList(String projectCheckTableId){
        LambdaUpdateWrapper<ProjectCheckTableRole> updateWrapper = new LambdaUpdateWrapper<ProjectCheckTableRole>()
                .eq(ProjectCheckTableRole::getProjectCheckTableId, projectCheckTableId);
        iProjectCheckTableRoleService.remove(updateWrapper);
    }


    private void saveProjectTableRoleIdList(List<String> roleIdList, String projectCheckTableId) {
        if(CollectionUtil.isNotEmpty(roleIdList)){
            List<ProjectCheckTableRole> projectCheckTableRoleList = new ArrayList<>();
            for (String roleId : roleIdList) {
                ProjectCheckTableRole projectCheckTableRole = new ProjectCheckTableRole();
                projectCheckTableRole.setProjectCheckTableId(projectCheckTableId);
                projectCheckTableRole.setOptRoleId(roleId);
                OptRole role = iOptRoleService.getById(roleId);
                if(role == null){
                    throw new CustomException("【参数错误】角色id不存在");
                }
                projectCheckTableRole.setRoleName(role.getName());
                projectCheckTableRoleList.add(projectCheckTableRole);
            }
            iProjectCheckTableRoleService.saveBatch(projectCheckTableRoleList);
        }
    }



}
